<template>
  <div id="app">
    <h1>接口设计与代码生成工具</h1>
    <form class="form-container">
      <label for="endpoint">接口路径:</label>
      <input type="text" v-model="endpoint" placeholder="/api/v1/users">

      <label for="method">HTTP 方法:</label>
      <select v-model="method">
        <option value="GET">GET</option>
        <option value="POST">POST</option>
        <option value="PUT">PUT</option>
        <option value="DELETE">DELETE</option>
      </select>
      <div id="kvPairContainer">
      <div v-for="(pair, index) in keyValuePairs" :key="index" class="kv-pair">
        <input type="text" v-model="pair.key" placeholder="键" @input="generateRequestBody">
        <input type="text" v-model="pair.value" placeholder="值" @input="generateRequestBody">
        <button @click.prevent="removeKvPair(index)">×</button>
      </div>
      <button @click.prevent="addKvPair">+</button>
    </div>

      <div v-if="showRequestBody" id="requestBodyContainer">
        <label for="requestBody">请求体:</label>
        <textarea name="requestBody" rows="5" v-model="requestBody"></textarea>
      </div>

      <button @click.prevent="generateCode">生成代码</button>
    </form>

    <div class="code-blocks">
      <div class="code-block">
        <h2>Java 类代码</h2>
        <pre><code v-html="javaClassCode"></code></pre>
      </div>
      <div class="code-block">
        <h2>Spring Boot Controller 函数代码</h2>
        <pre><code v-html="controllerFunctionCode"></code></pre>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watchEffect, onMounted } from 'vue';

const endpoint = ref('');
const method = ref('GET');
const keyValuePairs = ref([{ key: '', value: '' }]);
const showRequestBody = ref(false);
const requestBody = ref('');
const javaClassCode = ref('');
const controllerFunctionCode = ref('');

function addKvPair() {
  keyValuePairs.value.push({ key: '', value: '' });
  generateRequestBody();
}

function removeKvPair(index) {
  keyValuePairs.value.splice(index, 1);
  generateRequestBody();
}

function generateCode() {
  const javaClassCodeValue = generateJavaClassCode();
  const controllerFunctionCodeValue = generateControllerFunctionCode();
  javaClassCode.value = `<pre><code>${javaClassCodeValue}</code></pre>`;
  controllerFunctionCode.value = `<pre><code>${controllerFunctionCodeValue}</code></pre>`;
}

function generateJavaClassCode() {
  let code = `public class RequestModel {\n`;

  keyValuePairs.value.forEach((pair, index) => {
    const key = pair.key.trim();
    const value = pair.value.trim();
    if (key && value) {
      code += `  private String ${key};\n`;
      code += `  public String get${capitalize(key)}() {\n    return ${key};\n  }\n`;
      code += `  public void set${capitalize(key)}(String ${key}) {\n    this.${key} = ${key};\n  }\n`;
    }
  });

  code += `}`;

  return code;
}

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

function generateControllerFunctionCode() {
  const methodStr = method.value.toLowerCase();
  const path = endpoint.value;
  const requestClassName = 'RequestModel';
  const responseBody = `{ "message": "Success" }`;

  let code = '';

  if (methodStr === 'get') {
    code = `  @GetMapping("${path}")\n  public ResponseEntity<String> handleGet() {\n    return ResponseEntity.ok(${responseBody});\n  }\n`;
  } else if (methodStr === 'post') {
    code = `  @PostMapping("${path}")\n  public ResponseEntity<String> handlePost(@RequestBody ${requestClassName} request) {\n    // Example of using the request object\n    String someKey = request.getSomeKey();\n    return ResponseEntity.ok(${responseBody});\n  }\n`;
  } else if (methodStr === 'put') {
    code = `  @PutMapping("${path}")\n  public ResponseEntity<String> handlePut(@RequestBody ${requestClassName} request) {\n    // Example of using the request object\n    String someKey = request.getSomeKey();\n    return ResponseEntity.ok(${responseBody});\n  }\n`;
  } else if (methodStr === 'delete') {
    code = `  @DeleteMapping("${path}")\n  public ResponseEntity<String> handleDelete() {\n    return ResponseEntity.ok(${responseBody});\n  }\n`;
  }

  return code;
}

function generateRequestBody() {
  const body = keyValuePairs.value.reduce((acc, pair) => {
    const key = pair.key.trim();
    const value = pair.value.trim() || ""; // 如果值为空，则设为 ""
    const actualKey = key ? key : ""; // 如果键为空，则使用 ""
    acc[actualKey] = value;
    return acc;
  }, {});

  requestBody.value = JSON.stringify(body, null, 2);
}

 

function updateRequestBodyVisibility() {
  showRequestBody.value = !['GET', 'DELETE'].includes(method.value);
}

// Use watchEffect for cleaner syntax
watchEffect(() => {
  updateRequestBodyVisibility();
});
// 添加 watch 监听器

onMounted(() => {
  // 默认情况下只有一个键值对
  addKvPair();
});
</script>

<style scoped>
.code-blocks {
  display: flex;
  gap: 20px;
}

.code-block {
  border: 1px solid #ccc;
  padding: 10px;
  width: calc(50% - 10px);
  overflow-x: auto; /* 添加水平滚动条 */
  white-space: pre-wrap; /* 允许换行 */
}

#app {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
}

h1 {
  text-align: center;
  margin-top: 20px; /* 调整与顶部的距离 */
}

.form-container {
  width: 100%; /* 确保表单组件铺满整行 */
  max-width: 600px; /* 设置最大宽度以适应不同屏幕大小 */
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#kvPairContainer,
#requestBodyContainer {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.kv-pair {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

button,
input,
select,
textarea {
  width: 100%;
  padding: 5px;
  box-sizing: border-box;
}

button {
  cursor: pointer;
}

#response {
  margin-top: 20px;
  padding: 10px;
  background-color: #f8f9fa;
  border: 1px solid #dee2e6;
  border-radius: 5px;
  overflow-y: auto;
  max-height: 300px;
}
</style>